package com.codingman.data.mybatis.mapper;

import java.util.Optional;

import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;

import com.codingman.data.mybatis.support.DeleteSqlProvider;
import com.codingman.data.mybatis.support.InsertSqlProvider;
import com.codingman.data.mybatis.support.SelectSqlProvider;
import com.codingman.data.mybatis.support.UpdateSqlProvider;

public interface CrudMapper<T, ID> {
	
	@InsertProvider(type=InsertSqlProvider.class)
	<S extends T> Integer insert(S entity);
	
	@UpdateProvider(type=UpdateSqlProvider.class)
	<S extends T> Integer update(S entity);

	/**
	 * Retrieves an entity by its id.
	 *
	 * @param id must not be {@literal null}.
	 * @return the entity with the given id or {@literal Optional#empty()} if none found.
	 * @throws IllegalArgumentException if {@literal id} is {@literal null}.
	 */
	@SelectProvider(type=SelectSqlProvider.class)
	Optional<T> findById(@Param("id")ID id);

	/**
	 * Returns all instances of the type.
	 *
	 * @return all entities
	 */
	@SelectProvider(type=SelectSqlProvider.class)
	Iterable<T> findAll();

	/**
	 * Returns the number of entities available.
	 *
	 * @return the number of entities.
	 */
	@SelectProvider(type=SelectSqlProvider.class)
	long count();

	/**
	 * Deletes the entity with the given id.
	 *
	 * @param id must not be {@literal null}.
	 * @throws IllegalArgumentException in case the given {@literal id} is {@literal null}
	 */
	@DeleteProvider(type=DeleteSqlProvider.class)
	void deleteById(ID id);

	/**
	 * Deletes a given entity.
	 *
	 * @param entity must not be {@literal null}.
	 * @throws IllegalArgumentException in case the given entity is {@literal null}.
	 */
	@DeleteProvider(type=DeleteSqlProvider.class)
	void delete(T entity);

	/**
	 * Deletes all entities managed by the repository.
	 */
	@DeleteProvider(type=DeleteSqlProvider.class)
	void deleteAll();
	
	
}
